<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>v-for数组更新</title>
</head>
<body>

<div id="app">
    <ul>
        <template v-for="book in books">
            <li>书名：{{ book.name }}</li>
            <li>作者名： {{ book.author }}</li>
            <br/>
        </template>
    </ul>
</div>

<hr>

<div id="app1">
    <ul>
        <template v-for="book in books">
            <li>书名：{{ book.name }}</li>
            <li>作者名： {{ book.author }}</li>
            <br/>
        </template>
    </ul>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
    /**
     * Vue的核心是数据与视图的双向绑定，当我们修改数组时，Vue会检测到数据变化，所以用v-for渲染的视图也会立即更新。
     * Vue中包含了一组观察数据变化的方法，使用它们改变数组也会触发视图更新，(变异方法)
     * 如push()/pop()/shift()/unshift()/splice()/sort()/reverse()(注意上述方法会改变调用的原始数组),当然还可以借助于修改数组的引用
     *
     *
     * 但是filter()/concat()/slice()方法不会改变原来的数组，因为它们返回的是一个新的数组
     * **/


        //注意push()/pop()/shift()/unshift()/splice()/sort()/reverse()方法会改变调用的原始数组
    var app = new Vue({
            el: "#app",
            data: {
                books: [
                    {
                        name: "Java",
                        author: "test"
                    },
                    {
                        name: "JavaScript",
                        author: "hello",
                    },
                    {
                        name: "Python",
                        author: "envy",
                    },
                ]
            },
        });
    app.books.push({
        name: "hello,world",
        author: "bob",
    });


    //注意filter()/concat()/slice()方法不会改变调用的原始数组，而是返回一个新的数组
    var app1 = new Vue({
        el: "#app1",
        data: {
            books: [
                {
                    name: "Java",
                    author: "test"
                },
                {
                    name: "JavaScript",
                    author: "hello",
                },
                {
                    name: "Python",
                    author: "envy",
                },
            ]
        },
    });
    app1.books = app1.books.filter(function (item) {
        return item.name.match(/Java/);
    });


    /**
     *
     * Vue在检测到数组变化时，并不是直接重新渲染整个列表，而是最大化的复用DOM元素。
     * 替换的数组中，含有相同元素的项不会被重新渲染，因此可以大胆地使用新的数组来替换旧数组，不用担心性能问题
     * **/


    /**
     * 需要注意的是，以下两种变动的数组中，Vue是不能检测到的，因此不会触发视图更新
     * 1、通过索引直接设置项，如app.books[3]={......}
     *
     * 2、修改数组的长度，如app.books.length=1
     * **/

    //通过索引直接设置项，如app.books[3]={......}的解决办法

    //方法1：(导入Vue包)使用Vue内置的set方法
    // Vue.set(app.books,3,{
    //     name:"Go",
    //     author:"honor",
    // })


    //(未导入Vue包),在webpack中使用组件化的方式，默认没有导入Vue包，此时可以使用$set
    //注意此处的this指向就是当前组件的实例，即app在非webpack模式下也可以使用$set方法，如app.$set(...)
    // this.$set(app.books,3,{
    //      name:"Go",
    //      author:"honor",
    // })
    //上面的和下面的其实是一样的
    // app.$set(app.books, 3, {
    //     name: "Go",
    //     author: "honor",
    // })


    //方法2：使用splice()方法
    app.books.splice(3, 1, {
        name: "Go",
        author: "honor",
    });


    //修改数组的长度，如app.books.length=1的解决办法
    app.books.splice(4);   //设置数组的长度，注意这个是动态的

</script>
</body>
</html>